/*
 * Copyright (C) 2017-2019, AEye, Inc.
 * All rights reserved.
 */

#ifndef SENSOR_READER_HPP
#define SENSOR_READER_HPP

#include <atomic>
#include <cstdint>
#include <functional>
#include <memory>
#include <string>
#include <thread>

#include "PcapPacket.hpp"
#include "PointCloudFrame.hpp"
#include "SocketCloudReader.hpp"
#include "SocketDiagnosticReader.hpp"
#include "SocketHawkeyeReader.hpp"
#include "Sensor.hpp"
#include "HawkeyeFrame.hpp"

class SensorReader  {
public:

  SensorReader(std::string ipAddress, uint16_t cloudPort,
               uint16_t diagnosticPort, uint16_t hawkeyePort,
               std::string name, bool broadcastMode);

  ~SensorReader();

  const std::string &ipAddress() const;
  const std::string &name() const;
  void  setCloudCallback(const std::function<void(aeye::PointCloudFrame&&)>& processCallback);
  void  setDiagnosticCallback(const std::function<void(aeye::DiagnosticData&&)>& processCallback);
  void  processRangingPcapPacket(aeye::PcapPacket& packet);
  void  processDiagnosticPcapPacket(aeye::PcapPacket& packet);

  void  setHawkeyeCallback(const std::function<void(aeye::HawkeyeFrame&&)>& processCallback);

  void  start();
  void  stop();
  void  collectCloud();

  //Hawkeye
  void startHawkeye();
  void stopHawkeye();
  void collectHawkeyeBuffer();

  void startDiagnostic();
  void stopDiagnostic();
  void collectDiagnostic();


  void setPcapMode(bool value);
  void resetSocketReaders();

private:
  std::string _ipAddress;
  std::string _name;

  aeye::SocketCloudReader      cloudReader;
  aeye::SocketHawkeyeReader    hawkeyeReader;
  aeye::SocketDiagnosticReader diagnosticReader;

  std::atomic<bool> _isRunning;
  std::atomic<bool> isHawkeyeRunning;
  std::atomic<bool> isDiagnosticRunning;

  std::thread cloudSubscriber;
  std::thread cloudPublisher;

  std::thread hawkeyeSubscriber;
  std::thread hawkeyePublisher;

  std::thread diagnosticSubscriber;
  std::thread diagnosticPublisher;

  std::function<void(aeye::PointCloudFrame&&)> _pointCloudCallback = nullptr;
  std::function<void(aeye::DiagnosticData&&)>  _diagnosticCallback = nullptr;
  std::function<void(aeye::HawkeyeFrame&&)>  _hawkeyeCallback = nullptr;

};

#endif // SENSOR_READER_HPP
